package com.scrabbleMaster.lindo;

import java.util.Arrays;
import java.util.List;

import com.scrabbleMaster.lindo.model.Expression;
import com.scrabbleMaster.lindo.model.Model;

public class LindoExecutor extends com.lindo.Lindo {
	private static int nErrorCode[] = new int[1];
    private static StringBuffer cErrorMessage = new StringBuffer();
    private static StringBuffer cLicenseKey = new StringBuffer();
    
    static
    {
      // The runtime system executes a class's static
      // initializer when it loads the class.
      System.loadLibrary("lindojni");
    }
    
    
	public void executeTest() {
		/*
		 * Ejemplo z max
		 * 
		 * con z = a + b
		 * a < 10; b < 10;
		 */
		Object /*long*/ pEnv = null;
		pEnv = createEnviroment();
		
		/* >>> Step 2 <<< Create a model in the environment. */
        Object lindoModel = createModel(pEnv); 
        
        /* >>> Step 3 <<< Specify the model. */
        Model model = getModel();
        
        LSloadLPData( lindoModel, 
        		model.getConstraintsSize(), 
        		model.getInvolvedVariables().size(),
        		model.getDirection(), 
        		model.getObjectiveConstantValue(), 
        		model.getObjectiveCoeficients(), 
        		model.getConstraintsLimits(), 
        		model.getConstraintsTypes(), 
        		model.getNonzeroCoeficientsQuantityInConstraints(), 
        		model.getNonZeroColumnStartInConstraints(), 
        		null /*pnLenCol*/, 
        		model.getNonzeroCoeficientsInConstraints(), //<- mal el orden es 1, 2, 1, 1, deberia ser 1, 1, 2, 1
        		model.getRowIndexForNonZeroCoefficients(), //es 0, 0, 1, deberia ser 0, 1, 0, 2
        		model.getLowerVariablesBounds(), 
        		model.getUpperVariablesBounds());
            
        APIErrorCheck(pEnv);
        nErrorCode[0] = LSloadNameData(lindoModel, "MyTitle","MyObj",null,null,
            null,model.getConstraintNames().toArray(new String[0]),model.getInvolvedVariables().toArray(new String[0]),null);
        APIErrorCheck(pEnv);
        
        int nSolStatus[] = new int[1];
        /* >>> Step 4 <<< Perform the optimization */
        nErrorCode[0] = LSoptimize( lindoModel, LS_METHOD_PSIMPLEX, nSolStatus);
        APIErrorCheck(pEnv);
        
        
        double dObj[] = new double[1];
        /* Get the value of the objective */
        nErrorCode[0] = LSgetInfo(lindoModel, LS_DINFO_POBJ, dObj) ;
        APIErrorCheck(pEnv);

        System.out.print("Objective Value = " + dObj[0] + "\n");

        
        
        System.out.println("Fin de la corrida");
	}

	private Model getModel() {
		//Modelo de test
		// Z = 20*a + 30*C  -> MAX
		//ST: 
		//a + 2C  <= 120
		// a      <= 60;
		//C       <= 50
		List<Expression> constraints = Arrays.asList(
				Expression.named("Constraint1").with(1, "A").with(2, "C").lessThan(120.0),
				Expression.named("Constraint2").with(1, "A").lessThan(60.0),
				Expression.named("Constraint3").with(1, "C").lessThan(50.0));
		return Model.maximizer( Expression.named("objective").with(20,"A").with(30, "C") ).suchThat(constraints);
	}

	private Object createModel(Object pEnv) {
		Object model = LScreateModel ( pEnv, nErrorCode);
        APIErrorCheck(pEnv);
        return model;
	}


	private Object createEnviroment() {
		Object pEnv = null;
		/* >>> Step 1 <<< Read license file and create a LINDO environment. */
        nErrorCode[0] = this.LSloadLicenseString("c:/Users/Administrador/workspace/scrabble-master/license/lndapi70.lic",cLicenseKey);
        APIErrorCheck(pEnv);
        
        
		pEnv = this.LScreateEnv(nErrorCode, cLicenseKey.toString());
        APIErrorCheck(pEnv);
        
        return pEnv;
	}

	
	// Generalized error Reporting function
    private static void APIErrorCheck(Object /*long*/ pEnv )
    {
        if(0 != nErrorCode[0])
        {
            LSgetErrorMessage(pEnv, nErrorCode[0], cErrorMessage);
            System.out.println("\nError " + nErrorCode[0] + ": " + cErrorMessage);
            System.out.println();
            System.exit(1);
        }
    }
    
}
